namespace Core.Implementation
{
	using System;
	using System.Collections.Generic;
	using Infrastructure;
	using Microsoft.Practices.Unity;
	using NHibernate;

	internal class NHibernateDomainSession : DomainSession
	{
		private readonly IDictionary<Type, object> registeredRepositories =
			new Dictionary<Type, object>();

		public NHibernateDomainSession(IUnityContainer container, NHibernateSessionFactoryProvider sessionFactoryProvider)
		{
			this.ParentContainer = container;
			this.SessionFactoryProvider = sessionFactoryProvider;
		}

		public IUnityContainer ParentContainer
		{
			get;
			private set;
		}

		public NHibernateSessionFactoryProvider SessionFactoryProvider
		{
			get;
			private set;
		}

		private IUnityContainer sessionUnityContainer;
		public IUnityContainer SessionUnityContainer
		{
			get
			{
				if (this.sessionUnityContainer == null)
				{
					this.sessionUnityContainer =
						this.ParentContainer.CreateChildContainer();

					this.sessionUnityContainer.RegisterInstance(this.Session);
				}

				return this.sessionUnityContainer;
			}
		}

		private ISession session;
		public ISession Session
		{
			get
			{
				if (this.session == null)
				{
					this.session = 
						this.SessionFactoryProvider
						.CreateSessionFactory()
						.OpenSession();
				}

				return this.session;
			}
		}

		protected override TRepository EnsureRepostory<TRepository>()
		{
			if (this.registeredRepositories.ContainsKey(typeof(TRepository)) == false)
			{
				this.registeredRepositories[typeof(TRepository)] = 
					this.SessionUnityContainer.Resolve<TRepository>();
			}
			return (TRepository)this.registeredRepositories[typeof(TRepository)];
		}

		public override void Flash()
		{
			if (this.session != null)
			{
				this.Session.Flush();
			}
		}
	}
}